﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using ExcelLibrary.SpreadSheet;

namespace WinDerivate
{
    /// <summary>
    /// Представление в программе таблицы калибровки термопары 
    /// </summary> 
    public class CalibrationTableHolder
    {
        /// <summary>
        /// Используемый коэфициент усиления
        /// </summary>
        const float Gain = 218;
        /// <summary>
        /// Опорное напряжение АЦП
        /// </summary>
        const float Usup =5.0f;
        /// <summary>
        /// Максимальное значение отсчета с АЦП (10 бит)
        /// </summary>
        const int maxSample = 1024;
        /// <summary>
        /// Имя типа термопары (ХА, ХК, ...)
        /// </summary>
        public string ThermocoupleType;
        /// <summary>
        /// Таблица калибровки
        /// -1 -- означает отсутсвие калиброванного значения для данной температуры
        /// </summary>
        public float[] table;
        /// <summary>
        /// Максимальная температура в таблице
        /// </summary>
        public int maxTemp;
        /// <summary>
        /// Минимальная температура в таблице
        /// </summary>
        public int minTemp;
        /// <summary>
        /// Шаг по температуре в таблице (обычно 10 град.)
        /// </summary>
        public int stepTemp=10;

        public static CalibrationTableHolder Load(string filepath)
        {
            CalibrationTableHolder table=new CalibrationTableHolder();
            Workbook book = Workbook.Open(filepath);
            var sheet = book.Worksheets[0];
            // считаем число ячеек и шаг

            int n = int.Parse(sheet.Cells[1, 0].StringValue);
            table.stepTemp = int.Parse(sheet.Cells[1, 1].StringValue);

            table.minTemp = int.Parse(sheet.Cells[3, 0].StringValue);
            table.maxTemp = int.Parse(sheet.Cells[sheet.Cells.LastRowIndex, 0].StringValue);
            
            table.table = new float[n];
            
            for (int rowIndex = 3; rowIndex <= sheet.Cells.LastRowIndex; rowIndex++)
                table.table[rowIndex-3] = float.Parse(sheet.Cells[rowIndex, 1].StringValue);

            return table;
        }

        //линейная интерполяция
        public float computeTemp(int sampleADC)
        {
            float voltage = computeMilliVoltage(sampleADC);
            var pair = FindInterval(voltage);
            var a =  (temp(pair.Right) - temp(pair.Left)) / (table[pair.Right] - table[pair.Left]);
            var b =   temp(pair.Left) - a * table[pair.Left];
            return a * voltage + b ;
        }

        public float computeMilliVoltage(int sampleADC)
        {
            float voltage = sampleADC * Usup / maxSample;
            return 1000 * voltage / Gain;
        }

        //поиск интервала в калиб.таблице в который попадает значение
        private QiHe.CodeLib.Pair<int, int> FindInterval(float val)
        {
            if (val < table[0]) return new QiHe.CodeLib.Pair<int, int>(0, 0);
            if (val > table[table.Length - 1]) return new QiHe.CodeLib.Pair<int, int>(table.Length - 1, table.Length - 1);
            for (int i = 1; i < table.Length-1; i++)
            {
                if((val>=table[i-1])&&(val<table[i]))
                    return new QiHe.CodeLib.Pair<int, int>(i - 1, i);
            }
            // не возможно сюда попасть - в верху полное покрытие условиями
            return new QiHe.CodeLib.Pair<int, int>(int.MinValue, int.MaxValue);
        }

        private float temp(int idx)
        {
            return idx * stepTemp - Math.Abs(minTemp);
        }
    }
}
